#ifndef GAME_H
#define GAME_H

#include "Singleton.h"

#include <QDebug>
#include <QList>

class MazeFactory;
class MazeBuilder;

enum Direction { North, South, East, West };

class MapSite {
  public:
    MapSite();
    virtual ~MapSite();
    virtual void Enter() = 0;
    virtual QString type() const = 0;
};


class Room: public MapSite {
public:
    Room(){}
    Room(int roomNo);
    Room(const Room&);
    ~Room(){}

    MapSite* GetSide(Direction) const;
    void SetSide(Direction, MapSite*);

    virtual void Enter();
    virtual QString type() const;
    virtual int Id() const;
    virtual Room* Clone() const;
    virtual void Initialize(int n);

private:
    MapSite* _side[4];
    int _roomNumber;
};

class Wall: public MapSite {
public:
    Wall(){}
    ~Wall(){}
    virtual void Enter();
    virtual QString type() const;
    virtual Wall* Clone() const;
};


class Door: public MapSite {
public:
    Door(Room* = 0, Room* = 0);
    Door(const Door&);
    ~Door(){}

    virtual void Enter();
    virtual QString type() const;
    Room* OtherSideFrom(Room*);
    virtual void Initialize(Room*, Room*);
    virtual Door* Clone() const;

private:
    Room* _room1;
    Room* _room2;
    bool _isOpen;
};

class Person {
public:
    Person(QString n){ _name = n; }
    ~Person(){}
    virtual QString name() const { return _name; }

private:
    QString _name;
};

// 类适配器
class MapSitePerson: public MapSite, private Person {
public:
  MapSitePerson(QString n);
  virtual ~MapSitePerson(){}
  virtual void Enter() {}
  virtual QString type() const
  {
      return _name;
  }
private:
    QString _name;
};

// 对象适配器
class MapSitePerson2: public MapSite {
public:
  MapSitePerson2(Person*);
  virtual ~MapSitePerson2(){}
  virtual void Enter() {}
  virtual QString type() const
  {
      return _person->name();
  }
private:
    Person* _person;
};

class Maze {    // 迷宫
public:
    Maze();
    ~Maze();
    Maze(const Maze&);

    void AddRoom(Room*);
    Room* RoomNo(int) const;
    int GetRoomSize() const;
    virtual Maze* Clone() const;

private:
    QList<Room*> _rooms;
};


// 抽象工厂 - 单例
class MazeFactory{
public:
    static MazeFactory* Instance();

    virtual ~MazeFactory();
    virtual Maze* MakeMaze() const
    { return new Maze; }
    virtual Wall* MakeWall() const
    { return new Wall; }
    virtual Room* MakeRoom(int n) const
    { return new Room(n); }
    virtual MapSite* MakePerson(QString n) const
    { return (MapSite*)new MapSitePerson2(new Person(n)); }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    { return new Door(r1, r2); }

protected:
    MazeFactory();

private:
    static MazeFactory* _instance;
};


class MazeGame
{
public:
    MazeGame();
    ~MazeGame();

    Maze* CreateMaze(MazeFactory& factory);
    Maze* CreateMaze();

    virtual Maze* MakeMaze() const
    {
        return new Maze;
    }
    virtual Room* MakeRoom(int n) const
    {
        return new Room(n);
    }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    {
        return new Door(r1, r2);
    }
    virtual Wall* MakeWall() const
    {
        return new Wall;
    }
};

#endif // GAME_H
